#ifndef TIMER_TIMER_H
#define TIMER_TIMER_H

#include "TimeUnit.hpp"

#include <functional>
namespace DBServer {
namespace Base {
namespace Timer
{
    
// puer virtual class 
class Timer {
public:
    Timer() = default;
    virtual ~Timer() = default;

    virtual int add() = 0;
    virtual int del() = 0;
    virtual int mod() = 0;
    virtual bool empty() = 0;
    virtual unsigned size() = 0;
    virtual bool is_timeout() = 0;
};

class Timer_n {
public:

    Timer_n(std::function<void(void)>);

    Time clock;
    Timer_n *prev, *next;
    std::function<void(void)> cb;
};

class TimingList : public Timer {
public:
    TimingList();
    ~TimingList();

    auto add(Timer_n&) -> int;
    auto mod(Timer_n&) -> int;
    auto del(Timer_n&) -> int;
    auto size() -> unsigned;
    auto empty() -> bool;
    auto is_timeout() -> bool;
    auto inline top() -> Timer_n&;
private:

    /* the immplements of timer queue */
    auto inline push(Timer_n&) -> int;
    auto inline pop(Timer_n&) -> bool;
    auto inline erase(Timer_n*) -> bool;

    int add() { return 0; }
    int del() { return 0; }
    int mod() { return 0; } 

private:
    Timer_n *head, *tail;
    unsigned _size;
};

/**
 * 
 * 
*/
using time_tt = unsigned long long; 

class Timer_w {
public:
    Timer_w();
    ~Timer_w() = default;
    Timer_w(const Timer_w&);
    Timer_w(Timer_w&&) = delete;
    auto operator=(const Timer_w&) -> const Timer_w;

    int slot;
    int circle;
    std::function<void(void)> cb;
    Timer_w *next, *prev;
};

class TimingWheel {
public:

    // time -> tick
    // int  -> slot
    TimingWheel(time_tt, int);
    ~TimingWheel();

    
    auto add(Timer_w&) -> void;
    auto add(std::function<void(void)>, time_tt) -> const Timer_w&;
    auto mod(Timer_w&, time_tt, std::function<void(void)>*) -> bool;
    auto del(Timer_w&) -> bool;

private:
    auto set_cb(Timer_w*, std::function<void(void)>) -> void;
    auto set_circle(Timer_w*, time_tt) -> void;
    auto set_slot(Timer_w*, time_tt) -> void;
    auto _add_and_mod(Timer_w*) -> void;
    auto _del(Timer_w*) -> bool;

private:
    time_tt tick;
    // dynamic array
    Timer_w **wheel;
    time_tt circle_time; 
    int slots;
    int cur;
};

/**
 * 
 * 
*/


class Timer_h{
public:

    Timer_h(std::function<void(void)>&);

    Time clock;
    unsigned hole_index;
    std::function<void(void)> cb;
};

class TimingHeap : public Timer {
public:

    TimingHeap();
    ~TimingHeap();

    auto add(Timer_h&) -> int;
    auto mod(Timer_h&) -> int;
    auto del(Timer_h&) -> int;
    auto inline empty() -> bool;
    auto inline size() -> unsigned;
    auto is_timeout() -> bool;
    
private:

    /* the immplement of min_heap*/
    auto inline push(Timer_h&) -> int;
    auto inline top() -> Timer_h&;
    auto inline pop() -> bool;
    
    auto inline shift_down(Timer_h*, unsigned) -> void;
    auto inline shift_up( unsigned) -> void;
    auto inline erase(Timer_h*) -> int;


    auto inline dilatation() -> void;

    int add() { return 0; }
    int del() { return 0; }
    int mod() { return 0; }

private:
    Timer_h **heap;
    unsigned total;
    unsigned _size;
    Time tick;
};


} // namespace Timer
} // namespace Bace
} // namespace DBServer
#endif